package com.lx.idgenerator.autoconfigure.redis;

import org.springframework.beans.BeansException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @author wcy redis配置类 根据参数注入不同的Bean
 */
public class RedisConfiguration implements ApplicationContextAware {


    private ApplicationContext applicationContext;


    private RedisProperties redisProperties;

    private RedisProperties.Jedis jedis;

    private RedisProperties.Pool pool;

    private RedisProperties.Cluster cluster;


  /**
   * jedis连接池配置
   * @return
   */
    @Bean
    JedisPoolConfig jedisPoolConfig(){
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        if( null != pool){
          jedisPoolConfig.setMaxIdle(pool.getMaxIdle());
          jedisPoolConfig.setMinIdle(pool.getMinIdle());
          jedisPoolConfig.setMaxTotal(pool.getMaxTotal());
          jedisPoolConfig.setMaxWaitMillis(pool.getMaxWaitMillis());
          jedisPoolConfig.setTestOnBorrow(pool.isTestOnBorrow());
          jedisPoolConfig.setTestOnReturn(pool.isTestOnReturn());
          jedisPoolConfig.setTestOnCreate(pool.isTestOnReturn());
        }
        return jedisPoolConfig;

    }

  /**
   * jedis配置
   * @param jedisPoolConfig
   * @return
   */
    @Bean
    JedisConfiguration jedisClientConfiguration(JedisPoolConfig jedisPoolConfig){


      Boolean usePooling = jedis.getUsePooling();

      String clientName = jedis.getClientName();

      JedisConfiguration jedisConfiguration = new JedisConfiguration(usePooling, clientName, jedisPoolConfig);

      jedisConfiguration.setReadTimeout(jedis.getReadTimeout());
      jedisConfiguration.setConnectTimeout(jedis.getConnectTimeout());

      return jedisConfiguration;
    }


  /**
   * 单机配置
   *
   * @return
   */
  @Bean
  @ConditionalOnProperty(prefix = "id.gen.redis", name = "mode", havingValue = "standalone")
  StandaloneRedisConfiguration distributedRedisStandaloneConfiguration() {


    return new StandaloneRedisConfiguration(redisProperties.getHost(), redisProperties.getPassword());
  }



  /**
   * 单机版jedis连接工厂
   * @param standaloneRedisConfiguration
   * @param jedisConfiguration
   * @return
   */
    @Bean
    @ConditionalOnProperty(prefix = "id.gen.segment.redis", name = "mode", havingValue = "standalone")
    JedisConnectionFactory jedisSingleConnectionFactory(StandaloneRedisConfiguration standaloneRedisConfiguration, JedisConfiguration jedisConfiguration){
      return new JedisConnectionFactory(standaloneRedisConfiguration, jedisConfiguration);
    }



  @Bean
  @ConditionalOnProperty(prefix = "id.gen.segment.redis", name = "mode", havingValue = "standalone")
  RedisTemplate idGenRedisTemplate(JedisConnectionFactory jedisSingleConnectionFactory){
    RedisTemplate redisTemplate = new RedisTemplate();
    redisTemplate.setConnectionFactory(jedisSingleConnectionFactory);
    return redisTemplate;
  }

  //集群版
  @Bean
  @ConditionalOnProperty(prefix = "id.gen.segment.redis", name = "mode", havingValue = "cluster")
  ClusterRedisConfiguration redisClusterConfiguration(){

    Integer maxRedirects = cluster.getMaxRedirects();
    List<String> nodes = cluster.getNodes();
    String password = cluster.getPassword();
    ClusterRedisConfiguration clusterRedisConfiguration = new ClusterRedisConfiguration(nodes);
    clusterRedisConfiguration.setMaxRedirects(maxRedirects);
    clusterRedisConfiguration.setPassword(password);
    return clusterRedisConfiguration;
  }


  @Bean
  @ConditionalOnProperty(prefix = "id.gen.segment.redis", name = "mode", havingValue = "cluster")
  JedisConnectionFactory jedisClusterConnectionFactory(ClusterRedisConfiguration redisClusterConfiguration, JedisConfiguration jedisConfiguration){
    return new JedisConnectionFactory(redisClusterConfiguration, jedisConfiguration);
  }



  @Bean
  @ConditionalOnProperty(prefix = "id.gen.segment.redis", name = "mode", havingValue = "cluster")
  RedisTemplate idGenClusterRedisTemplate(JedisConnectionFactory jedisClusterConnectionFactory){
    RedisTemplate redisTemplate = new RedisTemplate();
    redisTemplate.setConnectionFactory(jedisClusterConnectionFactory);
    return redisTemplate;
  }



  @PostConstruct
  public void init() {
    redisProperties = applicationContext.getBean(RedisProperties.class);
    if(null != redisProperties){
      jedis = redisProperties.getJedis() != null ? redisProperties.getJedis(): new RedisProperties.Jedis();
      pool = jedis.getPool() != null ? jedis.getPool() : new RedisProperties.Pool();
      cluster = redisProperties.getCluster() != null ? redisProperties.getCluster() : new RedisProperties.Cluster();
    }else {
      redisProperties = new RedisProperties();
      jedis = new RedisProperties.Jedis();
      pool = new RedisProperties.Pool();
      cluster = new RedisProperties.Cluster();
    }

  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }

}
